//! # 安全配置
//!
//! 定义安全相关的配置结构和选项。

use serde::{Deserialize, Serialize};

/// 安全配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SecurityConfig {
    /// 密码策略
    pub password_policy: PasswordPolicy,
    /// 加密配置
    pub encryption_config: EncryptionConfig,
    /// 审计配置
    pub audit_config: AuditConfig,
    /// 限流配置
    pub rate_limit_config: RateLimitConfig,
    /// IP过滤配置
    pub ip_filter_config: IpFilterConfig,
    /// 安全头配置
    pub security_headers: SecurityHeadersConfig,
}

/// 密码策略
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PasswordPolicy {
    /// 最小长度
    pub min_length: u32,
    /// 最大长度
    pub max_length: u32,
    /// 是否需要小写字母
    pub require_lowercase: bool,
    /// 是否需要大写字母
    pub require_uppercase: bool,
    /// 是否需要数字
    pub require_numbers: bool,
    /// 是否需要特殊字符
    pub require_special_chars: bool,
    /// 特殊字符集合
    pub special_chars: String,
    /// 是否禁止常见密码
    pub forbid_common_passwords: bool,
    /// 密码历史限制（不能与最近N个密码相同）
    pub password_history_limit: u32,
    /// 密码有效期（天）
    pub password_expiry_days: Option<u32>,
}

/// 加密配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EncryptionConfig {
    /// 默认加密算法
    pub default_algorithm: String,
    /// 密钥长度
    pub key_length: u32,
    /// 盐长度
    pub salt_length: u32,
    /// 哈希迭代次数
    pub hash_iterations: u32,
    /// JWT签名算法
    pub jwt_algorithm: String,
    /// JWT签名密钥
    pub jwt_secret: String,
    /// 是否启用密钥轮换
    pub key_rotation_enabled: bool,
    /// 密钥轮换间隔（小时）
    pub key_rotation_interval_hours: u32,
}

/// 审计配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AuditConfig {
    /// 是否启用审计
    pub enabled: bool,
    /// 审计级别
    pub level: AuditLevel,
    /// 审计事件类型
    pub event_types: Vec<AuditEventType>,
    /// 审计输出配置
    pub output_config: AuditOutputConfig,
    /// 审计保留策略
    pub retention_policy: AuditRetentionPolicy,
}

/// 审计级别
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum AuditLevel {
    /// 最小审计（仅关键事件）
    Minimal,
    /// 标准审计
    Standard,
    /// 详细审计
    Detailed,
    /// 完整审计（所有事件）
    Complete,
}

/// 审计事件类型
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum AuditEventType {
    /// 认证事件
    Authentication,
    /// 授权事件
    Authorization,
    /// 会话事件
    Session,
    /// 密码事件
    Password,
    /// 配置变更事件
    Configuration,
    /// 系统事件
    System,
    /// 安全违规事件
    SecurityViolation,
}

/// 审计输出配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AuditOutputConfig {
    /// 输出类型
    pub output_types: Vec<AuditOutputType>,
    /// 文件输出配置
    pub file_config: Option<FileOutputConfig>,
    /// 数据库输出配置
    pub database_config: Option<DatabaseOutputConfig>,
    /// Syslog输出配置
    pub syslog_config: Option<SyslogOutputConfig>,
}

/// 审计输出类型
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum AuditOutputType {
    /// 控制台输出
    Console,
    /// 文件输出
    File,
    /// 数据库输出
    Database,
    /// Syslog输出
    Syslog,
    /// 远程服务器
    Remote,
}

/// 文件输出配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileOutputConfig {
    /// 文件路径
    pub file_path: String,
    /// 最大文件大小（MB）
    pub max_file_size_mb: u32,
    /// 最大文件数量
    pub max_files: u32,
    /// 是否压缩旧文件
    pub compress_old_files: bool,
}

/// 数据库输出配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DatabaseOutputConfig {
    /// 数据库连接URL
    pub connection_url: String,
    /// 表名
    pub table_name: String,
    /// 批量写入大小
    pub batch_size: u32,
    /// 写入超时（秒）
    pub write_timeout_seconds: u32,
}

/// Syslog输出配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SyslogOutputConfig {
    /// Syslog服务器地址
    pub server_addr: String,
    /// 协议类型
    pub protocol: SyslogProtocol,
    /// 设施代码
    pub facility: String,
    /// 应用程序名称
    pub app_name: String,
}

/// Syslog协议类型
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SyslogProtocol {
    Udp,
    Tcp,
    Tls,
}

/// 审计保留策略
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AuditRetentionPolicy {
    /// 保留天数
    pub retention_days: u32,
    /// 是否启用自动清理
    pub auto_cleanup_enabled: bool,
    /// 清理间隔（小时）
    pub cleanup_interval_hours: u32,
    /// 压缩配置
    pub compression_config: Option<CompressionConfig>,
}

/// 压缩配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CompressionConfig {
    /// 是否启用压缩
    pub enabled: bool,
    /// 压缩算法
    pub algorithm: CompressionAlgorithm,
    /// 压缩阈值（天，超过此天数的数据会被压缩）
    pub compression_threshold_days: u32,
}

/// 压缩算法
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum CompressionAlgorithm {
    Gzip,
    Zstd,
    Lz4,
}

/// 限流配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RateLimitConfig {
    /// 是否启用限流
    pub enabled: bool,
    /// 全局限流配置
    pub global_limit: RateLimit,
    /// 每用户限流配置
    pub per_user_limit: RateLimit,
    /// 每IP限流配置
    pub per_ip_limit: RateLimit,
    /// 限流算法
    pub algorithm: RateLimitAlgorithm,
    /// 限流存储类型
    pub storage_type: RateLimitStorageType,
}

/// 限流规则
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RateLimit {
    /// 请求数量
    pub requests: u32,
    /// 时间窗口（秒）
    pub window_seconds: u32,
    /// 突发允许量
    pub burst: u32,
}

/// 限流算法
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum RateLimitAlgorithm {
    /// 令牌桶
    TokenBucket,
    /// 漏桶
    LeakyBucket,
    /// 固定窗口
    FixedWindow,
    /// 滑动窗口
    SlidingWindow,
}

/// 限流存储类型
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum RateLimitStorageType {
    Memory,
    Redis,
}

/// IP过滤配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct IpFilterConfig {
    /// 是否启用IP过滤
    pub enabled: bool,
    /// 白名单
    pub whitelist: Vec<String>,
    /// 黑名单
    pub blacklist: Vec<String>,
    /// 是否启用地理位置过滤
    pub geo_filtering_enabled: bool,
    /// 允许的国家/地区代码
    pub allowed_countries: Vec<String>,
    /// 禁止的国家/地区代码
    pub blocked_countries: Vec<String>,
}

/// 安全头配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SecurityHeadersConfig {
    /// 是否启用安全头
    pub enabled: bool,
    /// X-Frame-Options
    pub x_frame_options: Option<String>,
    /// X-Content-Type-Options
    pub x_content_type_options: Option<String>,
    /// X-XSS-Protection
    pub x_xss_protection: Option<String>,
    /// Strict-Transport-Security
    pub strict_transport_security: Option<String>,
    /// Content-Security-Policy
    pub content_security_policy: Option<String>,
    /// Referrer-Policy
    pub referrer_policy: Option<String>,
    /// Permissions-Policy
    pub permissions_policy: Option<String>,
}

impl Default for SecurityConfig {
    fn default() -> Self {
        Self {
            password_policy: PasswordPolicy::default(),
            encryption_config: EncryptionConfig::default(),
            audit_config: AuditConfig::default(),
            rate_limit_config: RateLimitConfig::default(),
            ip_filter_config: IpFilterConfig::default(),
            security_headers: SecurityHeadersConfig::default(),
        }
    }
}

impl Default for PasswordPolicy {
    fn default() -> Self {
        Self {
            min_length: 8,
            max_length: 128,
            require_lowercase: true,
            require_uppercase: true,
            require_numbers: true,
            require_special_chars: true,
            special_chars: "!@#$%^&*()_+-=[]{}|;:,.<>?".to_string(),
            forbid_common_passwords: true,
            password_history_limit: 5,
            password_expiry_days: Some(90),
        }
    }
}

impl Default for EncryptionConfig {
    fn default() -> Self {
        Self {
            default_algorithm: "bcrypt".to_string(),
            key_length: 256,
            salt_length: 16,
            hash_iterations: 12,
            jwt_algorithm: "HS256".to_string(),
            jwt_secret: "default_jwt_secret_change_in_production".to_string(),
            key_rotation_enabled: false,
            key_rotation_interval_hours: 24 * 30, // 30天
        }
    }
}

impl Default for AuditConfig {
    fn default() -> Self {
        Self {
            enabled: true,
            level: AuditLevel::Standard,
            event_types: vec![
                AuditEventType::Authentication,
                AuditEventType::Authorization,
                AuditEventType::SecurityViolation,
            ],
            output_config: AuditOutputConfig::default(),
            retention_policy: AuditRetentionPolicy::default(),
        }
    }
}

impl Default for AuditOutputConfig {
    fn default() -> Self {
        Self {
            output_types: vec![AuditOutputType::Console, AuditOutputType::File],
            file_config: Some(FileOutputConfig::default()),
            database_config: None,
            syslog_config: None,
        }
    }
}

impl Default for FileOutputConfig {
    fn default() -> Self {
        Self {
            file_path: "/var/log/rustcloud-auth/audit.log".to_string(),
            max_file_size_mb: 100,
            max_files: 10,
            compress_old_files: true,
        }
    }
}

impl Default for AuditRetentionPolicy {
    fn default() -> Self {
        Self {
            retention_days: 90,
            auto_cleanup_enabled: true,
            cleanup_interval_hours: 24,
            compression_config: Some(CompressionConfig::default()),
        }
    }
}

impl Default for CompressionConfig {
    fn default() -> Self {
        Self {
            enabled: true,
            algorithm: CompressionAlgorithm::Gzip,
            compression_threshold_days: 30,
        }
    }
}

impl Default for RateLimitConfig {
    fn default() -> Self {
        Self {
            enabled: true,
            global_limit: RateLimit {
                requests: 10000,
                window_seconds: 60,
                burst: 100,
            },
            per_user_limit: RateLimit {
                requests: 100,
                window_seconds: 60,
                burst: 10,
            },
            per_ip_limit: RateLimit {
                requests: 1000,
                window_seconds: 60,
                burst: 50,
            },
            algorithm: RateLimitAlgorithm::TokenBucket,
            storage_type: RateLimitStorageType::Memory,
        }
    }
}

impl Default for IpFilterConfig {
    fn default() -> Self {
        Self {
            enabled: false,
            whitelist: vec![],
            blacklist: vec![],
            geo_filtering_enabled: false,
            allowed_countries: vec![],
            blocked_countries: vec![],
        }
    }
}

impl Default for SecurityHeadersConfig {
    fn default() -> Self {
        Self {
            enabled: true,
            x_frame_options: Some("DENY".to_string()),
            x_content_type_options: Some("nosniff".to_string()),
            x_xss_protection: Some("1; mode=block".to_string()),
            strict_transport_security: Some("max-age=31536000; includeSubDomains".to_string()),
            content_security_policy: Some("default-src 'self'".to_string()),
            referrer_policy: Some("strict-origin-when-cross-origin".to_string()),
            permissions_policy: Some("geolocation=(), microphone=(), camera=()".to_string()),
        }
    }
}

impl SecurityConfig {
    /// 验证安全配置
    pub fn validate(&self) -> Result<(), Vec<String>> {
        let mut errors = Vec::new();

        // 验证密码策略
        if let Err(mut password_errors) = self.password_policy.validate() {
            errors.append(&mut password_errors);
        }

        // 验证加密配置
        if let Err(mut encryption_errors) = self.encryption_config.validate() {
            errors.append(&mut encryption_errors);
        }

        if errors.is_empty() {
            Ok(())
        } else {
            Err(errors)
        }
    }
}

impl PasswordPolicy {
    /// 验证密码策略
    pub fn validate(&self) -> Result<(), Vec<String>> {
        let mut errors = Vec::new();

        if self.min_length == 0 {
            errors.push("Password minimum length must be greater than 0".to_string());
        }

        if self.max_length <= self.min_length {
            errors.push("Password maximum length must be greater than minimum length".to_string());
        }

        if self.min_length < 8 {
            errors.push("Password minimum length should be at least 8 characters for security".to_string());
        }

        if errors.is_empty() {
            Ok(())
        } else {
            Err(errors)
        }
    }

    /// 验证密码是否符合策略
    pub fn validate_password(&self, password: &str) -> Result<(), Vec<String>> {
        let mut errors = Vec::new();

        if password.len() < self.min_length as usize {
            errors.push(format!("Password must be at least {} characters long", self.min_length));
        }

        if password.len() > self.max_length as usize {
            errors.push(format!("Password must not exceed {} characters", self.max_length));
        }

        if self.require_lowercase && !password.chars().any(|c| c.is_lowercase()) {
            errors.push("Password must contain at least one lowercase letter".to_string());
        }

        if self.require_uppercase && !password.chars().any(|c| c.is_uppercase()) {
            errors.push("Password must contain at least one uppercase letter".to_string());
        }

        if self.require_numbers && !password.chars().any(|c| c.is_numeric()) {
            errors.push("Password must contain at least one number".to_string());
        }

        if self.require_special_chars && !password.chars().any(|c| self.special_chars.contains(c)) {
            errors.push("Password must contain at least one special character".to_string());
        }

        if errors.is_empty() {
            Ok(())
        } else {
            Err(errors)
        }
    }
}

impl EncryptionConfig {
    /// 验证加密配置
    pub fn validate(&self) -> Result<(), Vec<String>> {
        let mut errors = Vec::new();

        if self.key_length < 128 {
            errors.push("Key length should be at least 128 bits for security".to_string());
        }

        if self.salt_length < 8 {
            errors.push("Salt length should be at least 8 bytes".to_string());
        }

        if self.hash_iterations < 4 {
            errors.push("Hash iterations should be at least 4 for bcrypt".to_string());
        }

        if self.jwt_secret.len() < 32 {
            errors.push("JWT secret should be at least 32 characters long".to_string());
        }

        if errors.is_empty() {
            Ok(())
        } else {
            Err(errors)
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_security_config_default() {
        let config = SecurityConfig::default();
        assert!(config.audit_config.enabled);
        assert!(config.rate_limit_config.enabled);
        assert!(!config.ip_filter_config.enabled);
        assert!(config.security_headers.enabled);
    }

    #[test]
    fn test_password_policy_validation() {
        let policy = PasswordPolicy::default();
        
        // 测试有效密码
        assert!(policy.validate_password("SecurePass123!").is_ok());
        
        // 测试无效密码
        assert!(policy.validate_password("weak").is_err());
        assert!(policy.validate_password("alllowercase").is_err());
        assert!(policy.validate_password("ALLUPPERCASE").is_err());
        assert!(policy.validate_password("NoNumbers!").is_err());
        assert!(policy.validate_password("NoSpecialChars123").is_err());
    }

    #[test]
    fn test_encryption_config_validation() {
        let mut config = EncryptionConfig::default();
        assert!(config.validate().is_ok());

        config.key_length = 64; // 太短
        config.jwt_secret = "short".to_string(); // 太短
        
        let result = config.validate();
        assert!(result.is_err());
        
        let errors = result.unwrap_err();
        assert!(errors.iter().any(|e| e.contains("Key length should be at least 128 bits")));
        assert!(errors.iter().any(|e| e.contains("JWT secret should be at least 32 characters")));
    }

    #[test]
    fn test_enum_serialization() {
        let level = AuditLevel::Standard;
        let json = serde_json::to_string(&level).unwrap();
        assert_eq!(json, "\"standard\"");

        let algorithm = RateLimitAlgorithm::TokenBucket;
        let json = serde_json::to_string(&algorithm).unwrap();
        assert_eq!(json, "\"token_bucket\"");
    }

    #[test]
    fn test_rate_limit_config() {
        let config = RateLimitConfig::default();
        assert!(config.enabled);
        assert_eq!(config.global_limit.requests, 10000);
        assert_eq!(config.per_user_limit.requests, 100);
        assert_eq!(config.per_ip_limit.requests, 1000);
    }
}